home *** CD-ROM | disk | FTP | other *** search
- /*================================================================================
- dialogUtilities.c
- version 1.1
-
- Greg Anderson
- 28 June 1991
- greggor@apple.com
-
- This file contains various and sundry dialog box utility routines
-
- ================================================================================*/
- #include "dialogUtilities.h"
-
- #ifndef __TYPES__
- #include <Types.h>
- #endif
- #ifndef __SYSEQU__
- #include <SysEqu.h>
- #endif
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
- #ifndef __RESOURCES__
- #include <Resources.h>
- #endif
-
- /*
- #include <stdio.h>
- #include <string.h>
- */
- #ifndef __QUICKDRAW__
- #include <Quickdraw.h>
- #endif
- #ifndef __CONTROLS__
- #include <Controls.h>
- #endif
- #ifndef __DIALOGS__
- #include <Dialogs.h>
- #endif
-
- /*
- // I don't like these globals
- */
- short gDefaultButton = 1;
- short gDefaultUserItem = 0;
-
- /*--------------------------------------------------------------------------------
- Center the specified dialog box & show it
-
- This code centers the dialog box on the main monitor (the one with the
- menu bar) such that 1/3rd of the empty space left on that screen is
- above the dialog and 2/3rds of it is below the dialog
-
- Note:
-
- This routine looks at MBarHeight to correctly calculate the
- horizontal position of the dialog box. Accessing low memory
- globals is generally an evil thing to do, but in this case there\
- is no good alternative.
- --------------------------------------------------------------------------------*/
- pascal void CenterAndShowDialog(DialogPtr dlog)
- {
- short menuHeight;
- short dlogWidth;
- short dlogHeight;
- short scrnWidth;
- short scrnHeight;
- short newDlogX;
- short newDlogY;
-
- /*
- // Look at the low memory global 'MBarHeight' to determine the
- // height of the menu bar (in pixels)
- */
- menuHeight = *((short*)MBarHeight);
- /*
- // Calculate the size of the dialog box and the main screen
- // (without the menu bar)
- */
- dlogWidth = (dlog->portRect.right - dlog->portRect.left);
- dlogHeight = (dlog->portRect.bottom - dlog->portRect.top);
- scrnWidth = (qd.screenBits.bounds.right - qd.screenBits.bounds.left);
- scrnHeight = (qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) - menuHeight;
- /*
- // Quick check: don't leave any empty space if the dialog is
- // too large to fit on the main screen. This sanity check
- // really should not be necessary, though, as all dialog boxes
- // should fit on 9" screens
- */
- if( dlogHeight > scrnHeight)
- dlogHeight = scrnHeight;
- /*
- // Calculate the menu's new location
- */
- newDlogX = qd.screenBits.bounds.left + (scrnWidth - dlogWidth) / 2;
- newDlogY = qd.screenBits.bounds.top + menuHeight + (scrnHeight - dlogHeight) / 3;
- /*
- // Move the dialog and show it
- */
- MoveWindow(dlog,newDlogX,newDlogY,false);
- ShowWindow(dlog);
- }
-
- /*--------------------------------------------------------------------------------
- Creates a new useritem in the specified dialog box & returns its item number
- --------------------------------------------------------------------------------*/
- pascal short AddNewUserItem( DialogPtr dlog )
- {
- DialogPeek theDialog = (DialogPeek)dlog;
- short** itemHandle = (short**)theDialog->items;
- short nItems = **itemHandle + 1;
- short newItem = 0;
- DITLitem* ditlPtr;
- Size itemHandleSize;
-
- itemHandleSize = GetHandleSize( (Handle)itemHandle );
- SetHandleSize( (Handle)itemHandle, itemHandleSize + sizeof(DITLitem) );
- if( MemError() == noErr )
- {
- /*
- // We dereference the (potentially) unlocked itemHandle
- // here; don't do any memory-moving calls until we've
- // initialized the new DITL item
- */
- ditlPtr = (DITLitem*) ( (*itemHandle) + (itemHandleSize / sizeof(short)) );
- /*
- // Fill in the new fields
- */
- ditlPtr->placeholder = 0;
- ditlPtr->itemType = userItem;
- ditlPtr->extraLength = 0;
- /*
- // Remember / record the new number of items
- */
- newItem = nItems + 1;
- **itemHandle = newItem - 1;
- }
-
- return newItem;
- }
-
- /*--------------------------------------------------------------------------------
- Draw the thick rounded rectangle around the default button
-
- This routine uses Keith Rollin's algorithm, as presented in the
- USENET Guide to Programming the Macintosh. I have modified the
- basic algorithm only slightly--I add two to the calculated
- 'buttonOval' value. This gets better results, particularly for
- buttons of the default size (18 points).
- --------------------------------------------------------------------------------*/
- pascal void DrawDefaultProc(DialogPtr dlog, short item)
- {
- short type;
- Handle userHandle;
- ControlHandle buttonHandle = nil;
- Rect outlineBox;
- Rect buttonBox;
- PenState saveState;
- short buttonOval;
-
- GetPenState( &saveState );
- GetDItem(dlog, item, &type, &userHandle, &outlineBox);
- /*
- // We want to draw the thick line with a normal
- // pen pattern that is 3 pixels wide
- */
- PenNormal();
- PenSize(3,3);
- /*
- // If the button we are outlining is disabled,
- // draw the outline with a gray pattern.
- // (Don't forget to check if the default button
- // is disabled in your filterProc before translating
- // RETURN to a button click)
- //
- // The bad news is that we don't get a refCon to
- // go with our userItem, so we must resort to
- // the use of a global to keep track of the
- // default button. This isn't so bad, since an
- // application usually shouldn't have a
- // modal dialog box bring up another modal dialog
- // box. If your application does, just make sure
- // that you either (a) save & restore gDefaultButton,
- // or (b) make sure that both modal dialog boxes
- // use item #1 for their default button.
- */
- GetDItem(dlog, gDefaultButton, &type, (Handle*)&buttonHandle, &buttonBox);
- if( buttonHandle )
- {
- if( (*buttonHandle)->contrlHilite == 255 )
- PenPat(qd.gray);
- }
- /*
- // Calculate the curvature to use and draw the thick line
- */
- buttonOval = 2 + (outlineBox.bottom - outlineBox.top) / 2;
- FrameRoundRect(&outlineBox,buttonOval,buttonOval);
-
- SetPenState( &saveState );
- }
-
- /*--------------------------------------------------------------------------------
- This function creates a useritem around the default button & installs
- a drawing proc that draws the default border around it.
-
- If you want a button other than button #1 to act as the default button,
- don't forget to supply your own filterProc that translates RETURN to
- the correct item number.
- --------------------------------------------------------------------------------*/
- pascal short InstallDefaultOutline(DialogPtr dlog, short button)
- {
- short userItem;
- short type;
- Handle item;
- Rect box;
- Rect userBox;
-
- userItem = AddNewUserItem( dlog );
- if( userItem > 0 )
- {
- GetDItem(dlog, button, &type, &item, &box);
- InsetRect(&box,-4,-4);
- GetDItem(dlog, userItem, &type, &item, &userBox);
- SetDItem(dlog, userItem, type, (Handle)DrawDefaultProc, &box );
- }
-
- gDefaultButton = button;
- gDefaultUserItem = userItem;
-
- return userItem;
- }
-
- /*--------------------------------------------------------------------------------
- Draw the thick square rectangle around the dialog item that accepts
- keyboard input (see the System 7 Chooser for an example).
- --------------------------------------------------------------------------------*/
- pascal void DrawActiveItemProc(DialogPtr dlog, short item)
- {
- short type;
- Handle itemHandle;
- Rect box;
- PenState saveState;
-
- GetPenState( &saveState );
- GetDItem(dlog, item, &type, &itemHandle, &box);
- InsetRect(&box,1,1);
- PenNormal();
- PenSize(2,2);
- FrameRect(&box);
- SetPenState( &saveState );
- }
-
- /*--------------------------------------------------------------------------------
- This function creates a useritem around the specified button & installs
- a drawing proc that draws the default border around it.
-
- Note:
-
- This routine insets the button rect by -4, & the drawing proc insets this
- value again by 1. This may seem strange, but if we just inset the rect
- by -3 in this routine, then the same 'MoveOutline' function could not be
- used for both default button outlines and active item outlines.
- (MoveOutline always insets the item rect by -4)
- --------------------------------------------------------------------------------*/
- pascal short InstallActiveItemOutline(DialogPtr dlog, short button)
- {
- short userItem;
- short type;
- Handle item;
- Rect box;
- Rect userBox;
-
- userItem = AddNewUserItem( dlog );
- if( userItem > 0 )
- {
- GetDItem(dlog, button, &type, &item, &box);
- InsetRect(&box,-4,-4);
- GetDItem(dlog, userItem, &type, &item, &userBox);
- SetDItem(dlog, userItem, type, (Handle)DrawActiveItemProc, &box );
- }
-
- return userItem;
- }
-
- /*--------------------------------------------------------------------------------
- Move a userItem around the appropriate button.
-
- This function should be used in conjunction with InstallDefaultOutline and
- InstallActiveItemOutline to move the default button / active item indicator.
- --------------------------------------------------------------------------------*/
- pascal void MoveOutline(DialogPtr dlog, short userItem, short button)
- {
- short type;
- Handle item;
- Rect box;
- Rect userBox;
-
- GetDItem(dlog, button, &type, &item, &box);
- InsetRect(&box,-4,-4);
- GetDItem(dlog, userItem, &type, &item, &userBox);
- SetDItem(dlog, userItem, type, item, &box );
- /*
- // Erase the old box & invalidate the old and new
- // locations to force a redraw
- */
- EraseRect( &userBox );
- InvalRect( &userBox );
- InvalRect( &box );
-
- if( userItem == gDefaultUserItem )
- gDefaultButton = button;
- }
-
- /*----------------------------------------------------------------------
- Set the item handle of a dialog item (particularly useful for
- useritems)
- ----------------------------------------------------------------------*/
- pascal void SetItemHandle( DialogPtr dlog, short whichItem, Handle newItem )
- {
- short type;
- Handle item;
- Rect box;
-
- GetDItem(dlog,whichItem,&type,&item,&box);
- SetDItem(dlog,whichItem,type,newItem,&box);
- }
-
- /*--------------------------------------------------------------------------------
- Returns the location of a given dialog item
- --------------------------------------------------------------------------------*/
- Point GetItemPoint( DialogPtr dlog, short itemNum )
- {
- Point loc;
- short type;
- Handle item;
- Rect box;
-
- GetDItem(dlog,itemNum, &type, &item, &box);
- loc.h = box.left;
- loc.v = box.top;
- return( loc );
- }
-
- /*--------------------------------------------------------------------------------
- This simple routine will enable or disable a button
- --------------------------------------------------------------------------------*/
- pascal void EnableButton(DialogPtr dlog, short button,Boolean enable)
- {
- ControlHandle buttonHandle;
- short type;
- Rect box;
-
- GetDItem(dlog,button,&type,(Handle*)&buttonHandle,&box);
- HiliteControl(buttonHandle, enable ? 0 : 255);
- }
-